package cn.schoolwow.quickapi.module.business.apiController.service;

import cn.schoolwow.quickapi.domain.QuickAPIOption;
import cn.schoolwow.quickapi.module.business.apiController.domain.APIController;
import cn.schoolwow.quickapi.module.business.apiController.flow.SetControllerDeprecatedFlow;
import cn.schoolwow.quickapi.module.business.apiController.flow.SetControllerPrefixFlow;
import cn.schoolwow.quickapi.module.common.domain.APIDocument;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.util.domain.query.queryPackage.QueryPackage;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

public class SetAPIControllerListFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setControllerPackageClassName(flowContext);
        setAPIControllerList(flowContext);
        executeListener(flowContext);
    }

    @Override
    public String name() {
        return "设置API控制器列表流程";
    }

    private void setControllerPackageClassName(FlowContext flowContext){
        QuickAPIOption quickAPIOption = flowContext.checkInstanceData(QuickAPIOption.class);

        List<Class> controllerClazzList = new ArrayList<>();
        for(String packageName:quickAPIOption.controllerPackageNameList){
            List<Class> currentControllerClazzList = QueryPackage.newQuery(packageName)
                    .classNameSuffix("Controller")
                    .clazzRemovePredict(aClass -> {
                        if(null==aClass.getAnnotation(Controller.class)
                                &&null==aClass.getAnnotation(RestController.class)
                        ){
                            return true;
                        }
                        return false;
                    })
                    .execute()
                    .getClassList();
            if(null!=currentControllerClazzList&&!currentControllerClazzList.isEmpty()){
                controllerClazzList.addAll(currentControllerClazzList);
            }
        }

        if(controllerClazzList.isEmpty()){
            flowContext.broken("控制器列表查询为空");
        }
        flowContext.putTemporaryData("controllerClazzList", controllerClazzList);
    }

    private void setAPIControllerList(FlowContext flowContext){
        List<Class> controllerClazzList = flowContext.checkData("controllerClazzList", List.class);
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);

        List<APIController> apiControllerList = new ArrayList<>(controllerClazzList.size());
        for(Class clazz:controllerClazzList){
            APIController apiController = new APIController();
            apiController.clazz = clazz;
            apiController.className = clazz.getName();

            flowContext.startFlow(new SetControllerDeprecatedFlow())
                    .next(new SetControllerPrefixFlow())
                    .putCurrentCompositeFlowData("apiController", apiController)
                    .putCurrentCompositeFlowData("clazz", clazz)
                    .execute();

            apiControllerList.add(apiController);
        }
        apiDocument.apiControllerList = apiControllerList;
    }

    private void executeListener(FlowContext flowContext){
        QuickAPIOption quickAPIOption = flowContext.checkInstanceData(QuickAPIOption.class);

        if(null==quickAPIOption.apiControllerListener){
            return;
        }
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);
        for(APIController apiController:apiDocument.apiControllerList){
            quickAPIOption.apiControllerListener.handleAPIController(apiController);
        }
    }
}
